package com.wlf.server.common.config;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * Jackson,配置类
 */
@Configuration
public class JacksonConfig {
    /**
     * JSON，出入日期的全局处理，如果实体类上有格式注解以注解为准。
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> builder.modulesToInstall(getModel())
                // JSON中有的属性，但实体类中没有这个属性，默认true会报错，关闭false则不报错。
                .failOnUnknownProperties(true)
                // 为null的属性不进行序列化JSON的操作
                .serializationInclusion(JsonInclude.Include.NON_NULL)
                // 防止big-decimal科学计数法
                .featuresToEnable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)
                ;
    }

    /**
     * 功能描述: 自定义序列化
     *
     * @author wlf 2023/9/15 23:06
     */
    private JavaTimeModule getModel() {
        JavaTimeModule module = new JavaTimeModule();
        //localDateTime格式--yyyy-MM-dd HH:mm:ss
        module.addDeserializer(LocalDateTime.class,
                new JsonDeserializer<>() {
                    @Override
                    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                        return DateUtil.parse(p.getValueAsString()).toLocalDateTime();
                    }
                });
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
        // localDate格式化--yyyy-MM-dd
        module.addDeserializer(LocalDate.class,
                new JsonDeserializer<>() {
                    @Override
                    public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                        return DateUtil.parse(p.getValueAsString()).toLocalDateTime().toLocalDate();
                    }
                });
        module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
        // localTime格式化--HH:mm:ss
        module.addDeserializer(LocalTime.class,
                new JsonDeserializer<>() {
                    @Override
                    public LocalTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                        return DateUtil.parse(p.getValueAsString()).toLocalDateTime().toLocalTime();
                    }
                });
        module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
        // 解决Date的格式化
        module.addDeserializer(Date.class,
                new JsonDeserializer<>() {
                    @Override
                    public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                        return DateUtil.parse(p.getValueAsString());
                    }
                });
        module.addSerializer(Date.class,
                new JsonSerializer<>() {
                    @Override
                    public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                        gen.writeString(DateUtil.date(value).toString(DatePattern.NORM_DATETIME_PATTERN));
                    }
                });

        // 解决JSON大数字精度问题
        module.addSerializer(Long.TYPE, ToStringSerializer.instance);
        module.addSerializer(Long.class, ToStringSerializer.instance);
        module.addSerializer(BigInteger.class, ToStringSerializer.instance);
        // 有小数点的数字建议全部使用BigDecimal类型，否则会有精度丢失问题。double,or float超过两位小数都会有精度丢失的问题
        return module;
    }
}
